#include "EpollReactor.h"
#include<thread>
EpollReactor::EpollReactor()
{
    //创建epoll 树
    m_epfd= epoll_create(OPEN_SIZE);//创建红黑树
    if(m_epfd<0){
        cout<<"Error:create epolltree node fail!!"<<endl;
        return ;
    }
    //初始化
    event=new struct epoll_event[OPEN_SIZE];
    if(!event){
        cout<<"Error alloc epoll_event fail!!"<<endl;
        return ;
    }
    isstart=true;
}

EpollReactor::~EpollReactor()
{
}

void EpollReactor::setfdinfo(FdInfo info)
{
    this->m_info=info;
}

void EpollReactor::diapathcer(int timeout)
{
     
     int num=epoll_wait(m_epfd,event,OPEN_SIZE,timeout);  //1s
     for(int i=0;i<num;i++){
        int ev=event[i].events;
        int fd=event[i].data.fd;
        if(ev & EPOLLIN){  //读事件
            if(StorageFdInfo[fd].readcallback!=nullptr){
                int n=StorageFdInfo[fd].readcallback(StorageFdInfo[fd].getarg());
                if(n==0){
                   cout<<"close"<<fd<<endl;
                   removeFdinfo(fd);
                }
            }     
        }
        else if(ev & EPOLLOUT){  //写事件
            if(StorageFdInfo[fd].writecallback!=nullptr){
                int n=StorageFdInfo[fd].writecallback(StorageFdInfo[fd].getarg());
                if(n==0){
                   cout<<"close"<<fd<<endl;
                   removeFdinfo(fd);
                }
            }    
        }
        else if(ev & EPOLLRDHUP){  //断开连接
            if(StorageFdInfo[fd].writecallback!=nullptr){
                StorageFdInfo[fd].writecallback(StorageFdInfo[fd].getarg());
            } 
             cout<<"断开连接"<<fd<<endl;
             removeFdinfo(fd); 
        }
     }
}

void EpollReactor::run()
{
    while (isstart)
    {
       diapathcer();
    }   
}

void EpollReactor::addFdinfo(FdInfo info)
{
    //lock_guard<mutex>lg(Fdmutex);
    StorageFdInfo.insert(pair<int,FdInfo>(info.getsocket(),info));
}

void EpollReactor::removeFdinfo(int fd)
{
    //lock_guard<mutex>lg(Fdmutex);
    if(StorageFdInfo.find(fd)==StorageFdInfo.end()){
        return ;
    }
    StorageFdInfo.erase(fd);
    //关闭文件描述符
    close(fd);
}

int EpollReactor::add()
{
    addFdinfo(m_info);
    if(ctl(EPOLL_CTL_ADD)<0){
        cout<<"Error EPOLL_CTL_ADD fail"<<endl;
        return -1;
    }
    return 1;
}

int EpollReactor::remove()
{
    if(ctl(EPOLL_CTL_DEL)<0){
        cout<<"Error EPOLL_CTL_DEL fail"<<endl;
         return -1;
    }
    return 1;
}

int EpollReactor::modify()
{
    if(ctl(EPOLL_CTL_MOD)<0){
        cout<<"Error EPOLL_CTL_MOD fail"<<endl;
         return -1;
    }
    return 1;
}


void EpollReactor::SelectTask(FdInfo info, EventType type)
{
      setfdinfo(info);
      if(type==EventType::ADD){  
          add();
      }
      else if(type==EventType::DEL){
          remove();
      }
      else if(type==EventType::MODIF){
          modify();
      }
}

int EpollReactor::ctl(int opt)
{
    event->data.fd=m_info.getsocket();
    int fd=m_info.getsocket();
    int event1=0;
    if(m_info.getevent() == static_cast<int>(Event::READEVENT)){
       event1|=EPOLLIN;     
    }
    else if(m_info.getevent() == static_cast<int>(Event::WRITEEVENT)){
       event1 |=EPOLLOUT;
    }
    else if(m_info.getevent() == static_cast<int>(Event::DESTROYEVENT)){
       event1 |=EPOLLRDHUP;
    }
    event->events=event1;
    return epoll_ctl(m_epfd,opt,fd,event);
}
